﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Utilities
{
    public class Logger
    {
        private static LoggerBase _logger = null;

        /// <summary>
        /// Log an error message.
        /// </summary>
        /// <param name="message">Text of the message</param>
        /// <param name="id">Text ID of the error message</param>
        public static void LogErrorMessage (string id, string message)
        {
            InitLogger();
            _logger.LogMessage(id, message);
        }

        public static void LogErrorMessage(string id, string message, Exception e)
        {
            InitLogger();
            _logger.LogMessage(id, message, e);
        }

        /// <summary>
        /// Create a default logger
        /// </summary>
        private static void InitLogger()
        {
            if (_logger == null)
            {
                FileInfo fname = new FileInfo(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\DeepTalk\\logs\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".log");
                if (!fname.Directory.Exists)
                {
                    fname.Directory.Create();
                }
                _logger = new LoggerFile(fname);
            }
        }

        /// <summary>
        /// Zero out the testing info we have stored.
        /// </summary>
        public static void ResetTestLogging()
        {
            _logger = null;
        }


        /// <summary>
        /// The base logger class
        /// </summary>
        private abstract class LoggerBase
        {
            public abstract void LogMessage (string ID, string message);
            public abstract void LogMessage (string ID, string message, Exception e);
        }

        private class LoggerFile : LoggerBase
        {
            private FileInfo _file;
            public LoggerFile(FileInfo f)
            {
                _file = f;
            }

            /// <summary>
            /// Write to a file
            /// </summary>
            /// <param name="ID"></param>
            /// <param name="message"></param>
            public void LogMessage(StringBuilder msg)
            {
                StreamWriter wr = null;
                lock (this)
                {
                    try
                    {
                        _file.Refresh();
                        if (_file.Exists)
                        {
                            wr = new StreamWriter(_file.Open(FileMode.Append, FileAccess.Write));
                        }
                        else
                        {
                            wr = _file.CreateText();
                        }
                        wr.WriteLine(DateTime.Now.ToString() + " " + msg.ToString());
                    }
                    finally
                    {
                        if (wr != null)
                        {
                            wr.Close();
                        }
                    }
                }
            }

            public override void LogMessage(string ID, string message)
            {
                StringBuilder bld = new StringBuilder();
                bld.Append("(" + ID + ") " + message);
                LogMessage(bld);
            }

            public override void LogMessage(string ID, string message, Exception e)
            {
                StringBuilder bld = new StringBuilder();
                bld.AppendLine("(" + ID + ") " + message + ":");

                DumpException(bld, e);

                LogMessage(bld);
            }

            /// <summary>
            /// Recursively dumps an exception into the builder
            /// </summary>
            /// <param name="bld"></param>
            /// <param name="e"></param>
            private void DumpException(StringBuilder bld, Exception e)
            {
                bld.Append("  ");
                bld.AppendLine(e.Message);

                StringReader rdr = new StringReader(e.StackTrace);

                string l = "";
                while (l != null)
                {
                    l = rdr.ReadLine();
                    bld.Append("    ");
                    bld.AppendLine(l);
                }

                if (e.InnerException != null)
                {
                    bld.AppendLine("  Inner Exception: ");
                    DumpException(bld, e.InnerException);
                }
            }

        }

        /// <summary>
        /// Start using a file to write out the logger info.
        /// </summary>
        /// <param name="f"></param>
        public static void UseFileLogger(FileInfo f)
        {
            _logger = new LoggerFile(f);
        }
    }
}
